package com.myproject.myblogserver.filter;

import java.io.IOException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.lang.NonNull;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
import org.springframework.web.filter.OncePerRequestFilter;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerExecutionChain;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;

import com.myproject.myblogserver.config.SecurityConfig;
import com.myproject.myblogserver.utils.JwtUtil;

import jakarta.annotation.security.PermitAll;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

@Component
public class JwtAuthenticationFilter extends OncePerRequestFilter {

    @Autowired
    private RequestMappingHandlerMapping requestMappingHandlerMapping;

    @Override
    protected void doFilterInternal(@NonNull HttpServletRequest request,
            @NonNull HttpServletResponse response,
            @NonNull FilterChain filterChain)
            throws ServletException, IOException {

        if (isPublicPath(request)) {
            filterChain.doFilter(request, response);
            return;
        }

        String authHeader = request.getHeader("Authorization");
        if (authHeader == null || !authHeader.startsWith("Bearer ")) {
            sendError(response, "Missing or invalid Authorization header");
            return;
        }

        String token = authHeader.substring(7);
        if (!JwtUtil.validateToken(token)) {
            sendError(response, "Invalid or expired token");
            return;
        }

        // 从Token中提取用户名（假设JwtUtil可以解析）
        var userID = JwtUtil.extractUserIdFromAuthHeader(authHeader);

        // 创建Authentication对象，并设置权限（需根据实际情况获取）
        var authentication = new UsernamePasswordAuthenticationToken(
                userID,
                null,
                // 这里应添加用户的权限列表，例如从Token或数据库获取
                AuthorityUtils.NO_AUTHORITIES);

        // 将Authentication存入SecurityContext
        SecurityContextHolder.getContext().setAuthentication(authentication);

        filterChain.doFilter(request, response);
    }

    private void sendError(HttpServletResponse response, String message) throws IOException {
        response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
        response.getWriter().write(message);
        response.getWriter().flush();
    }

    private boolean isPublicPath(HttpServletRequest request) {
        // 检查预配置的公共路径
        String requestURI = request.getRequestURI();
        AntPathMatcher pathMatcher = new AntPathMatcher();
        for (String path : SecurityConfig.PUBLIC_PATHS) {
            if (pathMatcher.match(path, requestURI)) {
                return true;
            }
        }

        // 检查控制器方法上的@PermitAll注解
        return hasPermitAllAnnotation(request);
    }

    private boolean hasPermitAllAnnotation(HttpServletRequest request) {
        try {
            HandlerExecutionChain handlerExecutionChain = requestMappingHandlerMapping.getHandler(request);
            if (handlerExecutionChain != null) {
                Object handler = handlerExecutionChain.getHandler();
                if (handler instanceof HandlerMethod) {
                    HandlerMethod handlerMethod = (HandlerMethod) handler;
                    // 检查方法上的注解
                    PermitAll methodAnnotation = AnnotationUtils.findAnnotation(
                            handlerMethod.getMethod(), PermitAll.class);
                    // 检查类上的注解
                    PermitAll classAnnotation = AnnotationUtils.findAnnotation(
                            handlerMethod.getBeanType(), PermitAll.class);
                    return methodAnnotation != null || classAnnotation != null;
                }
            }
        } catch (Exception e) {
            // 异常处理（例如无匹配处理器）
        }
        return false;
    }
}